﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace ITSP_Instance_Generator
{
    class GeneratorTSPLIB : IGenerator
    {
        private static readonly Random Random = new Random(); //todo seed?
        public List<Node> Nodes { get; private set; } 
        public int MaxVisits { get; private set; }
        public int MinVisits { get; private set; }
        public int Bound { get; private set; }
        public int BoundDelta { get; private set; }
        public GeneratorTSPLIB(List<Node> nodes, int minVisits, int maxVisits, int bound, int boundDelta)
        {
            Nodes = nodes;
            MinVisits = minVisits >= 1 ? minVisits : 1;
            MaxVisits = maxVisits >= MinVisits ? maxVisits : MinVisits;
            Bound = bound;
            BoundDelta = boundDelta;
        }

        public GeneratorTSPLIB(String filePath, int minVisits, int maxVisits, int bound, int boundDelta)
            : this(ReadNodesTSPLIB(filePath), minVisits, maxVisits, bound, boundDelta)
        {
        }

        public Instance Generate()
        {
            List<Node> nodes = new List<Node>();
            bool firstNode = true;
            foreach (Node n in Nodes)
            {
                Node nCopy = n.Clone();
                if (firstNode)
                    nCopy.NumberOfVisits = 2;
                else
                    nCopy.NumberOfVisits = Random.Next(MinVisits, MaxVisits + 1);

                nodes.Add(nCopy);
                firstNode = false;
            }
            int bound = Random.Next(Math.Max(0, Bound-BoundDelta), Bound+BoundDelta + 1);
            return new Instance(nodes.ToArray(), bound, Generator.GenerateDistanceMatrix(Nodes));
        }

        public int GetTotalNrNodes() // todo !!!!!!!!!!!!!!!!! totalNrNodes klopt niet met definitie !!!!!!!!!!!!!!!!!!!!!!!
        {
            return Nodes.Count();
        }

        public static List<Node> ReadNodesTSPLIB(String filePath)
        {
            List<Node> nodes = new List<Node>();
            StreamReader file = new StreamReader(filePath);
            string line;
            bool reachedNodePositions = false;
            while ((line = file.ReadLine()) != null && line != "EOF" && line != "")
            {
                if (reachedNodePositions)
                {
                    String[] nodeData = Regex.Split(line.TrimStart(' '), " +");
                    Node newNode = new Node(Int32.Parse(nodeData[0]), 1, new Position(Int32.Parse(nodeData[1]), Int32.Parse(nodeData[2])));
                    nodes.Add(newNode);
                }
                if (line == "NODE_COORD_SECTION")
                    reachedNodePositions = true;
            }
            file.Close();
            return nodes;
        }
        public override string ToString()
        {
            return String.Format("tsp{0};{1};{2};{3};{4}", GetTotalNrNodes(), MinVisits, MaxVisits, Bound, BoundDelta);
        }
    }
}
